﻿
Public Class request
    Public ReadOnly command As String = Nothing
    Public ReadOnly argument As envelope = Nothing

    Public Sub New(ByVal cmd As String,
                   Optional ByVal arg As envelope = Nothing)
        'the data will be copied in pack_request
        Me.command = cmd
        Me.argument = arg
    End Sub
End Class

Public Class response
    Public ReadOnly found As Boolean = False
    Public ReadOnly result As Boolean = False
    Public ReadOnly argument As envelope = Nothing

    Public Sub New(ByVal found As Boolean,
                   Optional ByVal result As Boolean = False,
                   Optional ByVal argument As envelope = Nothing)
        assert(found OrElse Not result)
        Me.found = found
        Me.result = result
        Me.argument = argument
    End Sub
End Class

Friend Module _rc_pac_common
    Private Class names
        Public Const function_name As String = "fun"
        Public Const envelope As String = "env"
        Public Const command_found As String = "cmf"
        Public Const command_result As String = "cmr"
    End Class

    Public Function pack_request(ByVal r As request, ByRef rtn As envelope) As Boolean
        If r Is Nothing Then
            Return False
        Else
            Return pack_request(r.command, r.argument, rtn)
        End If
    End Function

    Private Function pack_request(ByVal command As String, ByVal en As envelope, ByRef rtn As envelope) As Boolean
        If isemptystring(command) Then
            Return False
        Else
            rtn = New envelope()
            Return rtn.add(names.function_name, New bytesString(command)) AndAlso
                   (en Is Nothing OrElse rtn.add(names.envelope, en))
        End If
    End Function

    Public Function unpack_request(ByVal i As envelope, ByRef r As request) As Boolean
        Dim cmd As String = Nothing
        Dim en As envelope = Nothing
        Return unpack_request(i, cmd, en) AndAlso eva(r, New request(cmd, en))
    End Function

    Private Function unpack_request(ByVal i As envelope, ByRef command As String, ByRef en As envelope) As Boolean
        If i Is Nothing Then
            Return False
        Else
            Return i.get(names.function_name, command) AndAlso
                   Not isemptystring(command) AndAlso
                   (i.get(names.envelope, en) OrElse eva(en, envelope.empty))
        End If
    End Function

    Public Function pack_response(ByVal r As response,
                                  ByRef rtn As envelope) As Boolean
        If r Is Nothing Then
            Return False
        Else
            Return pack_response(r.found, r.result, r.argument, rtn)
        End If
    End Function

    Public Function pack_response(ByVal r As response,
                                  ByVal rtn As pointer(Of envelope)) As Boolean
        Dim e As envelope = Nothing
        Return pack_response(r, e) AndAlso eva(rtn, e)
    End Function

    Private Function pack_response(ByVal found As Boolean,
                                   ByVal result As Boolean,
                                   ByVal en As envelope,
                                   ByRef rtn As envelope) As Boolean
        rtn = New envelope()
        Return rtn.add(names.command_found, New bytesBoolean(found)) AndAlso
               rtn.add(names.command_result, New bytesBoolean(result)) AndAlso
               rtn.add(names.envelope, en)
    End Function

    Public Function unpack_response(ByVal i As envelope,
                                    ByRef rtn As response) As Boolean
        Dim found As Boolean = False
        Dim result As Boolean = False
        Dim en As envelope = Nothing
        Return unpack_response(i, found, result, en) AndAlso eva(rtn, New response(found, result, en))
    End Function

    Public Function unpack_response(ByVal i As envelope,
                                    ByVal rtn As pointer(Of response)) As Boolean
        Dim r As response = Nothing
        Return unpack_response(i, r) AndAlso eva(rtn, r)
    End Function

    Private Function unpack_response(ByVal i As envelope,
                                     ByRef found As Boolean,
                                     ByRef result As Boolean,
                                     ByRef en As envelope) As Boolean
        If i Is Nothing Then
            Return False
        Else
            Return i.get(names.command_found, found) AndAlso
                   i.get(names.command_result, result) AndAlso
                   (i.get(names.envelope, en) OrElse eva(en, envelope.empty))
        End If
    End Function
End Module
